<template>
  <view class="container">
    <canvas 
      style="width: 500px; height: 360px;" 
      width="500"
      height="360"
      canvas-id="myCanvas" 
      id="myCanvas"
      @touchstart="touchstart"
    ></canvas>
    <view class="rightContent">
      <view class="editItem" v-for="(item, idx) in selectedDefectives" :key="item.uuid">
        <view class="itemSort">{{ item.sort }}</view>
        <uni-data-picker 
          ref="defectiveItem"
          :localdata="treeData" 
          popup-title="请选择瑕疵" 
          v-model="item.label"
          @change="e => onchange(e, idx)"
          style="font-size: 20px;"
          :map="{text: 'defectiveSpot', value: 'id'}"
          class="itemPicker"
        ></uni-data-picker>
        <uni-number-box 
          :min="0" 
          :max="999"
          :value="item.value"
          class="itemNumber"
          color="#fff"
          background="#1890ff"
          @change="(e) => valueChange(e, idx)" 
        />
        <uni-icons @click="() => delItem(item)" type="minus-filled" :size="48" color="#1890ff"></uni-icons>
      </view>
    </view>
  </view>
</template>

<script>
  import TEST_IMG from '@/static/img/cloth3.jpeg';
  import { deepClone } from '@/utils/deepClone.js'
  export default {
    props: {
      treeData: Array,
      modalDefective: Array,
      modalData: Array,
      callback: Function,
      image: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        height: 360,
        width: 500,
        context: null,
        KEY_FIELD: 'id',
        VALUE_KEY: 'defectiveSpot',
        colorOptions: [
          'rgba(141, 242, 105, 0.6)', 
          'rgba(255, 163, 163, 0.6)', 
          'rgba(120, 118, 244, 0.6)', 
          'rgba(251, 183, 106, 0.6)', 
          'rgba(110, 220, 247, 0.6)'
        ],
        gridSize: 8,
        signArr: [],
        selectInfo: {
          x: undefined,
          y: undefined
        },
        maskColor: 'rgba(255, 163, 163, 0.6)',
        max: 0,
        selectedDefectives: [],
        oldDefectives: [],
        adding: false
      }
    },
    mounted() {
      this.context = uni.createCanvasContext('myCanvas')
      this.initData()
      this.drawImage()
      if (this.modalData && this.modalData.length) {
        this.signArr = this.modalData
      }
      if (this.modalDefective && this.modalDefective.length) {
        this.oldDefectives = this.modalDefective
        this.selectedDefectives = this.modalDefective
      }
    },
    methods: {
      onLoad() {
        console.log('onLoad')
      },
      delItem(target) {
        this.oldDefectives = this.selectedDefectives.filter(item => item.sort !== target.sort)
        const curSort = target.sort
        if (!(curSort >= 0)) return
        const cloneData = deepClone(this.signArr)
        for (let i = 0; i < cloneData.length; i++) {
          for (let j = 0; j < cloneData[i].length; j++) {
            if (cloneData[i][j].sort === curSort) {
              cloneData[i][j].sort = undefined
              cloneData[i][j].value = undefined
              cloneData[i][j].text = undefined
              cloneData[i][j].isMask = false
              cloneData[i][j].positionInfo = {}
              this.max--
            } else if (cloneData[i][j].sort > curSort) {
              cloneData[i][j].sort -= 1
            }
          }
        }
        this.signArr = cloneData
      },
      onchange(e, idx) {
        const value = e.detail.value
				if (value.length) {
					this.selectedDefectives[idx].text = value?.[value.length - 1]?.text
				}
      },
			valueChange(val, idx) {
				this.selectedDefectives[idx].value = val
			},
      touchstart(event) {
        const {x, y} = this.convertMousePositionToCanvas(event)
        this.getMousePos({x, y})
      },
      convertMousePositionToCanvas(evnet) {
        const touch = evnet.touches[0]
        const x = touch.x // 计算canvas中的x坐标
        const y = touch.y  // 计算canvas中的y坐标
        return { x, y } // 返回canvas坐标
      },
      getMousePos({ x, y }) {
        this.oldDefectives = deepClone(this.selectedDefectives) 
        this.adding = true
        const sectionWidth = this.width / this.gridSize
        const sectionHeight = this.height / this.gridSize
        const xPos = Math.floor(x / sectionWidth)
        const yPos = Math.floor(y / sectionHeight)
        this.selectInfo.x = xPos
        this.selectInfo.y = yPos
        let curRect = this.signArr[yPos][xPos]
        if (curRect.sort >= 0) return
        curRect.isMask = true
        curRect.sort = ++this.max
        curRect.value = 1
        curRect.positionInfo = {
          sx: sectionWidth * xPos,
          sy: sectionHeight * yPos,
          dx: sectionWidth,
          dy: sectionHeight
        }
      },
      initData() {
        this.signArr = new Array(this.gridSize)
          .fill(new Array(this.gridSize).fill(''))
          .map((arr) => {
            arr = arr.map(() => {
              return { value: undefined, isMask: false }
            })
            return arr
          })
      },
      drawBgLine () {
        this.context.strokeStyle = 'rgb(240, 240, 240)'
        this.context.lineWidth = 1
        for (let i = 0; i <= this.gridSize; i++) {
          const w = this.width / this.gridSize
          this.context.beginPath()
          this.context.moveTo(w * i, 0)
          this.context.lineTo(w * i, this.height)
          this.context.stroke()
        }
        for (let i = 0; i <= this.gridSize; i++) {
          const h = this.height / this.gridSize
          this.context.beginPath()
          this.context.moveTo(0, h * i)
          this.context.lineTo(this.width, h * i)
          this.context.stroke()
        }
      },
      drawCusMask(positionInfo, sort) {
        const sectionWidth = this.width / this.gridSize
        const { sx, sy, dx, dy } = positionInfo
        this.context.fillStyle = this.maskColor
        this.context.fillRect(sx, sy, dx, dy)
        this.context.fillStyle = '#fff'
        this.context.strokeStyle = '#000'
        this.context.font = 'bold 22px Arial'
        this.context.fillText(sort, sx + sectionWidth / 2 - 8, sy + 30)
        this.context.strokeText(sort, sx + sectionWidth / 2 - 8, sy + 30)
      },
      drawImage() {
        this.context.clearRect(0, 0, this.width, this.height)
        try {
          this.context.drawImage(
            this.image,
            0,
            0,
            this.width,
            this.height
          )
          // 网格线条
          this.drawBgLine()
          // 选中的网格信息
          this.signArr.forEach((row) => {
            row.forEach((col) => {
              if (col.isMask) {
                this.drawCusMask(col.positionInfo, col.sort)
              }
            })
          })
          this.context.draw()
        } catch (error) {
          console.log("🚀 ~ file: defectiveModal.vue:84 ~ drawImage ~ error:", error)
        }
      }
    },
    watch: {
      gridSize: function() {
        this.initData()
        this.drawImage()
      },
      signArr: {
        handler: function(arr) {
          this.selectedDefectives  = []
          this.selectedDefectives = arr.reduce((prev, yArr) => {
            const list = yArr.reduce((p, xItem) => {
              if (xItem.sort >= 0) {
                p.push({
                  ...xItem,
                  uuid: this.getUuid(12, 12),
                })
              }
              return p
            }, [])
            prev.push(...list)
            return prev
          }, [])
          this.selectedDefectives = this.selectedDefectives.sort((a, b) => a.sort - b.sort)
          if (this.oldDefectives && this.oldDefectives.length) {
            this.selectedDefectives.forEach((item, idx) => {
              item.value = this.oldDefectives?.[idx]?.value || item.value
              item.label = this.oldDefectives?.[idx]?.label || item.label
              item.text = this.oldDefectives?.[idx]?.text || item.text
            })
          }
          this.drawImage()
          if (this.adding) {
            this.adding = false
            this.$nextTick(() => {
              console.log(this.selectedDefectives.length, 'this.selectedDefectives.length');
              this.$refs[`defectiveItem`][this.selectedDefectives.length - 1].show()
            })
          }
          this.callback(arr, this.selectedDefectives)
        },
        deep: true 
      },
      selectedDefectives: {
        handler: function(arr) {
          this.callback(this.signArr, arr)
        },
        deep: true
      }
    }
  }
</script>

<style less="lang" scoped>
.container {
  display: flex;
  gap: 16px;
}
#myCanvas {
  box-sizing: border-box;
  border: 1px solid #e0e0e0;
}
.editItem {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}
.itemSort {
  margin-right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 500;
  color: #fff;
  width: 32px;
  height: 32px;
  background-color: #1890ff;
  border-radius: 50%;
}
.itemPicker {
  width: 380px;
  margin-right: 4px;
}
.item {
  padding-top: 12px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.colorCard {
  width: 36px;
  height: 24px;
  border-radius: 4px;
  cursor: pointer;
}
.label {
  width: 80px;
}
.rightContent {
  display: block;
  height: calc(100vh - 180px);
  overflow-y: auto;
}
</style>